Skip to content

fix: solve #3028 — forward DA1 query responses during shell init#3030

Merged
Kitenite merged 1 commit into
mainfrom
triage/issue-3028-23758493792
Mar 30, 2026
Merged

fix: solve #3028 — forward DA1 query responses during shell init#3030
Kitenite merged 1 commit into
mainfrom
triage/issue-3028-23758493792

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Mar 30, 2026

Summary

  • Fish shell sends DA1 (ESC[c) at startup to detect terminal capabilities, but the response was dropped during the "pending" shell-ready state, causing a 10-second timeout
  • Removed the shellReadyState === "pending" gate from the headless emulator's onData callback so query responses (DA1, DSR, etc.) are forwarded to the subprocess immediately
  • Added two tests proving DA1 and DSR responses are forwarded during shell init

Root cause

In session.ts, the headless emulator's onData callback had a guard that dropped all terminal query responses while shellReadyState === "pending". This was intended to prevent responses from appearing as typed text, but the headless emulator writes directly to the PTY (via sendWriteToSubprocess), not through the pre-ready stdin queue. The shell reads these as protocol data, not user input.

Fish sends DA1 during this exact "pending" window and waits up to 10 seconds for a reply. Without a response, fish disables cursor shape changes, reflow detection, and other optional features.

Test plan

  • New test: DA1 response forwarded to subprocess during pending state (fish shell)
  • New test: DSR response forwarded to subprocess during pending state (zsh)
  • Existing shell-ready tests continue to pass (19 tests)
  • Existing session tests pass (39 tests)
  • Headless emulator tests pass (21 tests)
  • Lint clean

Closes #3028


Summary by cubic

Forward terminal query responses (DA1, DSR) from the headless emulator during shell init so shells like fish don’t hang for 10s or disable features. Fixes #3028.

  • Bug Fixes
    • Removed the shellReadyState === "pending" guard in the headless emulator onData so DA1/DSR responses are written to the PTY immediately.
    • Added tests verifying DA1 (fish) and DSR (zsh) responses are forwarded during the pending state.

Written for commit e807b39. Summary will update on new commits.

Fish shell sends a DA1 escape sequence (ESC[c) at startup to detect
terminal capabilities. The headless emulator (xterm.js) correctly
generates a response, but it was being dropped during the "pending"
shell-ready state. This caused fish to wait 10 seconds before timing
out and disabling optional features like cursor shape and reflow.

The fix removes the shellReadyState gate from the headless emulator's
onData callback. Unlike renderer-generated responses (which go through
session.write() and are correctly dropped to avoid appearing as typed
text), headless emulator responses are written directly to the PTY and
consumed by the shell as protocol data.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@Kitenite Kitenite merged commit 3194568 into main Mar 30, 2026
1 check passed
@github-actions
Copy link
Copy Markdown
Contributor Author

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ⚠️ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

zombopanda added a commit to zombopanda/superset that referenced this pull request Mar 31, 2026
The `emulator.onData` callback only forwarded terminal query responses
(DA1, DSR) to the PTY subprocess when `attachedClients.size === 0`.
When a renderer client is attached (the normal case when viewing a
terminal), the headless emulator's DA1 response was silently dropped.

This caused fish shell to wait 10 seconds for a DA1 response that
never arrived, then print:
  "warning: fish could not read response to Primary Device Attribute
  query after waiting for 10 seconds"

The previous fix in superset-sh#3030 removed the `shellReadyState === "pending"`
guard but left the `attachedClients.size === 0` check intact. The
renderer's xterm also generates DA1 responses, but those go through
`write()` which drops all escape sequences during shell init — so
neither path delivered the response to fish.

Remove the `attachedClients.size === 0` condition so the headless
emulator always forwards query responses to the subprocess. This is
safe because `sendWriteToSubprocess` writes directly to the PTY via
IPC, bypassing the renderer's write path entirely.

Fixes superset-sh#3028
Kitenite added a commit that referenced this pull request Apr 3, 2026
Kitenite added a commit that referenced this pull request Apr 3, 2026
Kitenite added a commit that referenced this pull request Apr 3, 2026
The `emulator.onData` callback only forwarded terminal query responses
(DA1, DSR) to the PTY subprocess when `attachedClients.size === 0`.
When a renderer client is attached (the normal case when viewing a
terminal), the headless emulator's DA1 response was silently dropped.

This caused fish shell to wait 10 seconds for a DA1 response that
never arrived, then print:
  "warning: fish could not read response to Primary Device Attribute
  query after waiting for 10 seconds"

The previous fix in #3030 removed the `shellReadyState === "pending"`
guard but left the `attachedClients.size === 0` check intact. The
renderer's xterm also generates DA1 responses, but those go through
`write()` which drops all escape sequences during shell init — so
neither path delivered the response to fish.

Remove the `attachedClients.size === 0` condition so the headless
emulator always forwards query responses to the subprocess. This is
safe because `sendWriteToSubprocess` writes directly to the PTY via
IPC, bypassing the renderer's write path entirely.

Fixes #3028

Co-authored-by: zombopanda <1810282+zombopanda@users.noreply.github.com>
Co-authored-by: Kiet Ho <hoakiet98@gmail.com>
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 5, 2026
MocA-Love pushed a commit to MocA-Love/superset that referenced this pull request Apr 5, 2026
…rset-sh#3054)

The `emulator.onData` callback only forwarded terminal query responses
(DA1, DSR) to the PTY subprocess when `attachedClients.size === 0`.
When a renderer client is attached (the normal case when viewing a
terminal), the headless emulator's DA1 response was silently dropped.

This caused fish shell to wait 10 seconds for a DA1 response that
never arrived, then print:
  "warning: fish could not read response to Primary Device Attribute
  query after waiting for 10 seconds"

The previous fix in superset-sh#3030 removed the `shellReadyState === "pending"`
guard but left the `attachedClients.size === 0` check intact. The
renderer's xterm also generates DA1 responses, but those go through
`write()` which drops all escape sequences during shell init — so
neither path delivered the response to fish.

Remove the `attachedClients.size === 0` condition so the headless
emulator always forwards query responses to the subprocess. This is
safe because `sendWriteToSubprocess` writes directly to the PTY via
IPC, bypassing the renderer's write path entirely.

Fixes superset-sh#3028

Co-authored-by: zombopanda <1810282+zombopanda@users.noreply.github.com>
Co-authored-by: Kiet Ho <hoakiet98@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Primary Device Attribute (DA1) query response support

1 participant